// Fill out your copyright notice in the Description page of Project Settings.


#include "AnimatedActor.h"

AAnimatedActor::AAnimatedActor()
{
 	PrimaryActorTick.bCanEverTick = true;
	_reversed = false;
	
	static ConstructorHelpers::FObjectFinder<UCurveFloat> curveAsset(TEXT("/Game/MyCurve"));
	if (curveAsset.Succeeded()) _curve = curveAsset.Object;

	_spline = CreateDefaultSubobject<USplineComponent>(TEXT("MovingSpline"));
	_spline->SetupAttachment(GetRootComponent());

	_mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
	_mesh->SetupAttachment(_spline);

	static ConstructorHelpers::FObjectFinder<UStaticMesh> cubeAsset(
		TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube'"));
	if (cubeAsset.Succeeded())
	{
		_mesh->SetStaticMesh(cubeAsset.Object);
		_mesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
	}
}

void AAnimatedActor::BeginPlay()
{
	Super::BeginPlay();
	if (_curve == NULL) return;

	_spline->ClearSplinePoints();
	_spline->AddSplineWorldPoint(FVector(0.0, 0.0, 30.0));
	_spline->AddSplineWorldPoint(FVector(250.0, 200.0, 350.0));
	_spline->AddSplineWorldPoint(FVector(400.0, 0.0, 150.0));
	_spline->AddSplineWorldPoint(FVector(250.0, -200.0, 350.0));
	_spline->SetClosedLoop(true);

	const FVector location = _spline->GetLocationAtSplinePoint(0, ESplineCoordinateSpace::World);
	_mesh->SetWorldLocation(location);

	FOnTimelineFloat timelineProgress;
	timelineProgress.BindUFunction(this, TEXT("OnTimelineProcess"));
	_timeline.AddInterpFloat(_curve, timelineProgress);

	FOnTimelineEvent timelineFinish;
	timelineFinish.BindUFunction(this, TEXT("OnTimelineDone"));
	_timeline.SetTimelineFinishedFunc(timelineFinish);

	_timeline.SetPlayRate(0.2f);
	_timeline.SetTimelineLengthMode(TL_LastKeyFrame);
	_timeline.PlayFromStart();
}

void AAnimatedActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (_timeline.IsPlaying())
		_timeline.TickTimeline(DeltaTime);
}

void AAnimatedActor::OnTimelineProcess(float v)
{
	const float length = _spline->GetSplineLength();
	const FVector currentLocation =
		_spline->GetLocationAtDistanceAlongSpline(v * length, ESplineCoordinateSpace::World);
	FRotator currentRotation =
		_spline->GetRotationAtDistanceAlongSpline(v * length, ESplineCoordinateSpace::World);
	currentRotation.Pitch = 0.0f;
	_mesh->SetWorldLocationAndRotation(currentLocation, currentRotation);
}

void AAnimatedActor::OnTimelineDone()
{
	if (_reversed) { _timeline.PlayFromStart(); _reversed = false; }
	else { _timeline.Reverse(); _reversed = true; }
	UE_LOG(LogTemp, Warning, TEXT("Spline animation is ended. Now reversing..."));
}
